

#ifndef VULKAN3DRENDER_H_
#define VULKAN3DRENDER_H_
#include <QWindow>
#include <vsg/all.h>
#include <vsgQt/Viewer.h>

struct Vertex
{
  vsg::vec3 pos;
  vsg::vec3 normal;
  vsg::ivec3 ijk;
  vsg::vec4 uv;
  vsg::vec4 uv1;
  vsg::vec4 uv2;
};
struct RenderData
{
  vsg::ref_ptr<vsg::vec3Array> vertices  = nullptr;
  vsg::ref_ptr<vsg::vec3Array> normals   = nullptr;
  vsg::ref_ptr<vsg::vec3Array> ijks      = nullptr;
  vsg::ref_ptr<vsg::vec4Array> texcoords = nullptr;
  void SetPointSize(size_t numPoints)
  {
    vertices  = vsg::vec3Array::create(numPoints);
    normals   = vsg::vec3Array::create(numPoints);
    ijks      = vsg::vec3Array::create(numPoints);
    texcoords = vsg::vec4Array::create(numPoints);
  }
  void SetIndicesSize(size_t size)
  {
    indices = vsg::intArray::create(size);
  }
  void From(std::vector<vsg::vec3>& verts, std::vector<int>& indexs) {}
  vsg::ref_ptr<vsg::intArray> indices;
  vsg::box box;
};

class ScenePick : public vsg::Inherit<vsg::Visitor, ScenePick>
{
public:
  ScenePick() = default;
  explicit ScenePick(class vsgUI* uiWindow, vsg::ref_ptr<vsg::Camera> camera, vsg::ref_ptr<vsg::Camera> pickcamera, vsg::ref_ptr<vsg::Viewer> viewer,
                     vsg::ref_ptr<vsg::Device> device, vsg::ref_ptr<vsg::Image> captureIJKImage, vsg::ref_ptr<vsg::Image> locationImage);
  void apply(vsg::ButtonPressEvent& buttonPress) override;
  void apply(vsg::MoveEvent& event) override;
  vsg::ivec3 GetPickID()
  {
    return mPickID;
  }

protected:
  vsg::ref_ptr<vsg::Data> getImageData(vsg::ref_ptr<vsg::Viewer> viewer, vsg::ref_ptr<vsg::Device> device, vsg::ref_ptr<vsg::Image> captureImage);
  void saveImage(vsg::Path const& filename, vsg::ref_ptr<vsg::Viewer> viewer, vsg::ref_ptr<vsg::Device> device, vsg::ref_ptr<vsg::Image> captureImage,
                 vsg::ref_ptr<vsg::Options> options);

  void CalcPickID(int x, int y, vsg::ivec3& outPickID, vsg::vec3& outLocation);

  vsg::ref_ptr<vsg::Camera> mCamera = nullptr;
  vsg::ref_ptr<vsg::LookAt> mLookAt = nullptr;

  vsg::ref_ptr<vsg::Camera> mPickCamera = nullptr;
  vsg::ref_ptr<vsg::LookAt> mpickLookAt = nullptr;

  vsg::ref_ptr<vsg::Image> mIJKImage;
  vsg::ref_ptr<vsg::Image> mLocationImage;
  vsg::ref_ptr<vsg::Device> mDevice;
  vsg::ref_ptr<vsg::Viewer> mViewer;
  VkSubresourceLayout mSubResourceLayout;
  int mWidth;
  int mHeight;
  vsg::ivec3 mPickID;
  vsg::vec3 mPickLocation;
  class vsgUI* mUIWindow;
};

struct RenderNode
{
  vsg::ref_ptr<vsg::MatrixTransform> sceneNode;
  vsg::ref_ptr<vsg::MatrixTransform> sceneNodePick;
  vsg::ref_ptr<vsg::MatrixTransform> sceneNodeWireFrame;
};

struct RenderNodeRefNode
{
  vsg::ref_ptr<vsg::MatrixTransform> sceneNodePick;
  vsg::ref_ptr<vsg::MatrixTransform> sceneNodeWireFrame;
};

typedef std::map<vsg::ref_ptr<vsg::MatrixTransform>, RenderNodeRefNode> MAP_RENDERNODE_REF;

void generateCylinderMesh(const vsg::vec3& P1, const vsg::vec3& P2, float radius, int segments, std::vector<vsg::vec3>& vertices,
                          std::vector<int>& indices, int offset);

class Dream3DRender
{
public:
  Dream3DRender(class QMainWindow* QtMainWindow);
  ~Dream3DRender();
  // 初始化
  QWidget* Initialization();
  // 添加网格显示数据
  RenderNode AddRenderData(RenderData* render, bool resetCamera = false);
  // 获取拾取的ijk
  vsg::ivec3 GetPickID();
  // 设置色表文件
  void SetTextureColorTable(QString path);
  // 设置显示的属性字段序号
  void SetFiledIndexShow(int id);
  // 设置节点透明度
  void SetTransparency(RenderNode& node, float alpha);
  // 设置灯光强度
  void SetLightSrength(double l);
  // 设置网格显示信息
  void SetGridLineShowDistance(RenderNode& node,float distance, vsg::vec3 color, bool bOn);
  // 设置节点可见性
  void SetVisible(RenderNode& node, bool bVisible);
  // 高亮显示指定的IJK单元格
  void HighLightShowGridCell(vsg::ivec3 ijk);
  // 设置节点比例尺
  void SetScale(RenderNode& node, vsg::dvec3 scale);
  // 删除网格节点
  void RemoveRenderNode(RenderNode& node);
  // 重置场景位置
  void ResetScene();

protected:
  void CreatePipeline();
  void ResetUniformBuffer();
  vsgQt::Window* createWindow(vsg::ref_ptr<vsgQt::Viewer> viewer, vsg::ref_ptr<vsg::WindowTraits> traits, QWindow* parent, const QString& title = {});
  float mNearClipDistance = 1.0;
  float mFarClipDistance  = 100000.0;

private:
  class vsgUI* mUIMainWindow = nullptr;

  vsg::ref_ptr<vsg::Device> mDevice   = nullptr;
  vsg::ref_ptr<vsg::Context> mContext = nullptr;
  vsg::ref_ptr<vsg::Window> mWindow   = nullptr;

  vsg::ref_ptr<vsgQt::Viewer> mViewer     = nullptr;
  vsg::ref_ptr<vsg::LookAt> mlookAt       = nullptr;
  vsg::ref_ptr<vsg::Camera> mCamera       = nullptr;
  vsg::ref_ptr<vsg::Trackball> mTrackBall = nullptr;

  vsg::ref_ptr<vsg::Camera> mPickCamera = nullptr;
  vsg::ref_ptr<vsg::LookAt> mPicklookAt = nullptr;
  vsg::ref_ptr<ScenePick> mPickHandle   = nullptr;

  vsg::ref_ptr<vsg::Group> Main_Scene          = nullptr;
  vsg::ref_ptr<vsg::StateGroup> Main_ScenePick = nullptr;

  vsg::ref_ptr<vsg::StateGroup> Main_SceneOpaque    = nullptr;
  vsg::ref_ptr<vsg::StateGroup> Main_SceneWireframe = nullptr;
  vsg::ref_ptr<vsg::StateGroup> Main_SceneOpacity   = nullptr;

  vsg::ref_ptr<vsg::CommandGraph> main_RenderGraph        = nullptr;
  vsg::ref_ptr<vsg::CommandGraph> main_RenderGraphOpacity = nullptr;

  vsg::ref_ptr<vsg::CommandGraph> Main_CommandGraph        = nullptr;
  vsg::ref_ptr<vsg::CommandGraph> Main_CommandGraphOpacity = nullptr;

  //
  vsg::ref_ptr<vsg::ubvec4Array2D> mCurrentImageBuffer;
  int mCurrentField      = 0;
  float mCurrentDistance = 4000.0;
  float mAlpha           = 1.0;
  float mLightSrength    = 1.0;

  vsg::ref_ptr<vsg::vec3Value> uniformMyColorValue;
  vsg::ref_ptr<vsg::ivec3Value> uniformIJKValue;

  vsg::ref_ptr<vsg::vec2Value> WireFrameShowDistance;

  vsg::ref_ptr<vsg::ColorBlendState> mColorBlendState     = nullptr;
  vsg::ref_ptr<vsg::DepthStencilState> mDepthStencilState = nullptr;

  vsg::ref_ptr<vsg::MatrixTransform> DebugTransform;

  vsg::box mCurrentBox;

  // MAP_RENDERNODE_REF    mSceneNode_RerNodes;
};

#endif  // !1
